package voidlib;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.xml.ws.http.HTTPException;
import models.User;
import voidlib.menu.*;

public abstract class VoidController extends AbstractController {
    
    protected ModelAndView mav;
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    public static HttpSession session;
    protected Map<String, Object> view;
    protected String action;
    protected String controller;
    protected String layout = "default";
    
    protected VoidMenu menu;
    
    public VoidController() {
    }
    
    protected void initRequestParameterers() {
        action = request.getParameter("act");
        if (action == null) {
            action = "index";
        }
        controller = this.getClass().getName().replaceAll("Controller", "").toLowerCase().replaceAll("main.", "");
        
        this.view.put("actionName", action);
        this.view.put("className", controller);
        menu = new VoidMenu();
        this.view.put("menuItems", menu.items);
        this.view.put("VoidUser", VoidUser.getInstance());
        this.view.put("VoidHelper", VoidHelper.getInstance());
    }
    
    protected void init() {
        
    }
    
    @Override
    protected ModelAndView handleRequestInternal(
            HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        this.request = request;
        this.response = response;
        this.view = new HashMap<String, Object>();
        initSession();
        initRequestParameterers();
        init();
        
        dispatchRequest();
        
        
        VoidUser.getInstance().user = null;
        return this.mav;
    }
    
    protected void initModelAndView() {
        this.mav = new ModelAndView("layouts/" + this.layout, this.view);
    }
    
    protected void redirect(String target) {
        response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
        response.setHeader("Location", target);
        response.setContentType("text/html");
    }

    public static void setMessage(String message) {
        if (session.getAttribute("flashMessage") != null) {
            return;
        }
        session.setAttribute("flashMessage", message);
    }
    
    protected String _getParam(String name) {
        return this.request.getParameter(name);
    }
    
    protected void initSession() {
        session = request.getSession(true);
        Object roleObj = session.getAttribute("role");
        if (roleObj == null) {
            roleObj = "Guest";
        }
        String roleStr = roleObj.toString();
        UserRole role = UserRole.valueOf(roleStr.trim());
        if (role == null) {
            role = UserRole.Guest;
            session.setAttribute("role", role);
        } else {
            VoidUser.getInstance().login = (String)session.getAttribute("login");
        }
        VoidUser.getInstance().role = role;
        
        Object message = session.getAttribute("flashMessage");
        if (message != null) {
            this.view.put("flashMessage", message.toString());
            session.removeAttribute("flashMessage");
        }
    }
    
    protected boolean isPostRequest() {
        return this.request.getMethod().toLowerCase().compareTo("post") == 0;
    }
    
    protected void dispatchRequest() throws Exception{
        Method[] methods = this.getClass().getMethods();
        String desiredMethod = action.toLowerCase() + "action";
        boolean methodFound = false;
        for (int i = 0; i < methods.length; i++) {
            String methodName = methods[i].getName().toLowerCase().replaceAll("_", "");
            if (methodName.compareTo(desiredMethod) == 0)  {
                methods[i].invoke(this);
                methodFound = true;
            }
        }
        if (!methodFound) {
            throw new HTTPException(404);
        }
        
    }
    
    
}
